#include "game_log.h"
#include "game_macros.h"
#include <string.h>
#include <stdarg.h>

// using namespace CGame::Logger;


std::string CGame::Logger::priorityToStr(PriorityLevel_t priority)
{
  switch(priority) {
  case LOG4C_PRIORITY_FATAL:
    return "FATAL";
  case LOG4C_PRIORITY_ALERT:
    return "ALERT";
  case LOG4C_PRIORITY_CRIT:
    return "CRIT";
  case LOG4C_PRIORITY_ERROR:
    return "ERROR";
  case LOG4C_PRIORITY_WARN:
    return "WARN";
  case LOG4C_PRIORITY_NOTICE:
    return "NOTICE";
  case LOG4C_PRIORITY_INFO:
    return "INFO";
  case LOG4C_PRIORITY_DEBUG:
    return "DEBUG";
  case LOG4C_PRIORITY_TRACE:
    return "TRACE";
  case LOG4C_PRIORITY_NOTSET:
    return "NOTSET";
  default:
    return "UNKNOWN";
  }
}
CGame::Logger::PriorityLevel_t CGame::Logger::priorityFromStr(std::string priority)
{
  if (priority == "FATAL") {
    return LOG4C_PRIORITY_FATAL;
  } else if (priority == "ALERT") {
    return LOG4C_PRIORITY_ALERT;
  } else if (priority == "CRIT") {
    return LOG4C_PRIORITY_CRIT;
  } else if (priority == "ERROR") {
    return LOG4C_PRIORITY_ERROR;
  } else if (priority == "WARN") {
    return LOG4C_PRIORITY_WARN;
  } else if (priority == "NOTICE") {
    return LOG4C_PRIORITY_NOTICE;
  } else if (priority == "INFO") {
    return LOG4C_PRIORITY_INFO;
  } else if (priority == "DEBUG") {
    return LOG4C_PRIORITY_DEBUG;
  } else if (priority == "TRACE") {
    return LOG4C_PRIORITY_TRACE;
  } else if (priority == "NOTSET") {
    return LOG4C_PRIORITY_NOTSET;
  } else {
    return LOG4C_PRIORITY_UNKNOWN;
  }
}



void __fatal(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  __ccfatal("root",format, args);
  va_end(args);
}

void __ccfatal(const char* name,const char *format, ...)
{
  va_list args;
  va_start(args, format);

  __ccfatal(name,format,args);
  va_end(args);
}

void __ccfatal(const char* name,const char* format,va_list a_args){
  CGameLogger *logger = CGameLoggerFactory::getInstance()->getLogger(name);
  logger->fatal(format, a_args);
}


void __trace(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  __cctrace("root",format, args);
  va_end(args);
}

void __cctrace(const char* name,const char *format, ...)
{
  va_list args;
  va_start(args, format);

  __cctrace(name,format,args);
  va_end(args);
}

void __cctrace(const char* name,const char* format,va_list a_args){
  CGameLogger *logger = CGameLoggerFactory::getInstance()->getLogger(name);
  logger->trace(format, a_args);
}

void __debug(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  __ccdebug("root",format,args);
  va_end(args);
}

void __ccdebug(const char* name,const char *format, ...)
{
  va_list args;
  va_start(args, format);

  __ccdebug(name,format,args);
  va_end(args);
}

void __ccdebug(const char* name,const char* format,va_list a_args){
  CGameLogger *logger = CGameLoggerFactory::getInstance()->getLogger(name);
  logger->debug(format, a_args);
}

void __cclog(const char* name,const char *format, ...)
{
  va_list args;
  va_start(args, format);

  __cclog(name,format,args);
  va_end(args);
}

void __cclog(const char* name,const char* format,va_list a_args){
  CGameLogger *logger = CGameLoggerFactory::getInstance()->getLogger(name);
  logger->info(format, a_args);
}

void __log(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  // CGameLogger *logger = CGameLoggerFactory::getInstance()->getLogger(name);
  // logger->info(format, args);
  __cclog("root",format,args);
  va_end(args);
}

void __warn(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  __ccwarn("root",format, args);
  va_end(args);
}

void __ccwarn(const char* name,const char *format, ...)
{
  va_list args;
  va_start(args, format);

  __ccwarn(name,format,args);
  va_end(args);
}

void __ccwarn(const char* name,const char* format,va_list a_args){
  CGameLogger *logger = CGameLoggerFactory::getInstance()->getLogger(name);
  logger->warn(format, a_args);
}

void __error(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  __ccerror("root",format, args);
  va_end(args);
}

void __ccerror(const char* name,const char *format, ...)
{
  va_list args;
  va_start(args, format);

  __ccerror(name,format,args);
  va_end(args);
}

void __ccerror(const char* name,const char* format,va_list a_args){
  CGameLogger *logger = CGameLoggerFactory::getInstance()->getLogger(name);
  logger->error(format, a_args);
}


CGameLogger *CGameLoggerFactory::newLogger(const std::string &name)
{
  CGameLogger *logger = new CGameLogger(name.c_str());
  logger->init(getPriority());

  if (name == "root")
  {
    // __logger_init(logger, this);
    log4c_category_set_appender(logger->_logCategory, this->_log4c_appender);
    // log4c_category_set_appender(_logCategory, g_LoggerFactory._log4c_appender_file);
    log4c_category_set_priority(logger->_logCategory, getPriority());
  }

  return logger;
}

CGameLogger *CGameLoggerFactory::getLogger(const std::string &name)
{
  CGame::Logger::logger_map_t::iterator itr = _maps.find(name);
  CGameLogger *logger;
  if (_maps.end() != itr)
  {
    logger = itr->second;
  }
  else
  {
    logger = newLogger(name);
    _maps.insert(std::make_pair(name, logger));
  };

  return logger;
}

std::vector<std::string> CGameLoggerFactory::getLoggerList()
{
  std::vector<std::string> list;
  for (const auto &itr : _maps)
  {
    list.push_back(itr.first);
  }
  return list;
}

BOOL CGameLogger::init(CGame::Logger::PriorityLevel_t priority)
{

  do
  {
    _logCategory = log4c_category_get(_name.c_str());
    setPriority(priority);
    return TRUE;
  } while (true);

  return FALSE;
}

void CGameLogger::debug(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  debug(format, args);
  va_end(args);
}

void CGameLogger::debug(const char *format, va_list args)
{
  if (!log4c_category_is_debug_enabled(_logCategory)) {
    return;
  }
  log4c_category_vlog(_logCategory, LOG4C_PRIORITY_DEBUG, format, args);
}

void CGameLogger::fatal(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  fatal(format, args);
  va_end(args);
}

void CGameLogger::fatal(const char *format, va_list args)
{
  if (!log4c_category_is_fatal_enabled(_logCategory)) {
    return;
  }
  log4c_category_vlog(_logCategory, LOG4C_PRIORITY_FATAL, format, args);
}

void CGameLogger::info(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  info(format, args);
  va_end(args);
}

void CGameLogger::info(const char *format, va_list args)
{
  if (!log4c_category_is_info_enabled(_logCategory)) {
    return;
  }
  log4c_category_vlog(_logCategory, LOG4C_PRIORITY_INFO, format, args);
}

void CGameLogger::error(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  error(format, args);
  va_end(args);
}

void CGameLogger::error(const char *format, va_list args)
{
  if (!log4c_category_is_error_enabled(_logCategory)) {
    return;
  }
  log4c_category_vlog(_logCategory, LOG4C_PRIORITY_ERROR, format, args);
}

void CGameLogger::warn(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  warn(format, args);
  va_end(args);
}

void CGameLogger::warn(const char *format, va_list args)
{
  if (!log4c_category_is_warn_enabled(_logCategory)) {
    return;
  }
  log4c_category_vlog(_logCategory, LOG4C_PRIORITY_WARN, format, args);
}

void CGameLogger::trace(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  trace(format, args);
  va_end(args);
}

void CGameLogger::trace(const char *format, va_list args)
{
if (!log4c_category_is_trace_enabled(_logCategory)) {
    return;
  }
  log4c_category_vlog(_logCategory, LOG4C_PRIORITY_TRACE, format, args);
}

void CGameLogger::setPriority(CGame::Logger::PriorityLevel_t priority)
{
  if (NULL != _logCategory)
  {
    log4c_category_set_priority(_logCategory, priority);
    _priority = priority;
  }
}
